package com.auxgroup.smarthome.snoti.client;

import com.auxgroup.smarthome.snoti.Setting;
import com.auxgroup.smarthome.snoti.events.IPushEvent;
import com.gizwits.noti2.client.Command;
import com.gizwits.noti2.client.DataCommand;
import com.gizwits.noti2.client.Events;
import com.gizwits.noti2.client.LoginData;
import com.gizwits.noti2.client.NotiClient;
import com.gizwits.noti2.client.PushEvents;
import com.gizwits.noti2.client.RemoteControlData;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 * @Author: laiqiuhua.
 * @Date: 2017/9/4 14:42.
 */
public class NotiBootrap {
    private static final Logger logger = LoggerFactory.getLogger(NotiBootrap.class);
    private NotiClient notiClient = null;
    private String host = Setting.getValue("gizwits.noti.host").trim();
    private int port = Integer.parseInt(Setting.getValue("gizwits.noti.port").trim());;
    private int prefetchCount = 50; // <uint> (0 < prefetch_count <= 32767, 表示推送没有 ACK 的消息

    private Map<PushEvents, IPushEvent> callbacks = new HashMap<>();

    public NotiBootrap() {
        super();
        notiClient = connect(host, port);
    }

    private NotiClient connect(String host, int port) {
        return NotiClient.build().setHost(host).setPort(port);
    }

    public void setHost(String host) {
        notiClient.setHost(host);
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
        notiClient.setPort(port);
    }

    /**
     * 单PK登录
     * @param product_key
     * @param auth_id
     * @param auth_secret
     * @param subkey
     * @param events
     * @return
     */
    public NotiClient loginNoti(String product_key, String auth_id, String auth_secret, String subkey, List<Events> events) {
        notiClient = notiClient.login(product_key, auth_id, auth_secret, subkey, prefetchCount, events);
        notiClient.doStart();
        return notiClient;
    }

    /**
     * 多PK登录
     * @param datas
     * @return
     */
    public NotiClient loginNoti(List<LoginData> datas) {
        notiClient = notiClient.login(prefetchCount, datas);
        notiClient.doStart();
        return notiClient;
    }

    public void  start() {
        notiClient.doStop();
    }

    public void stop() {
        notiClient.doStop();
    }

    public void restart() {
        notiClient.restart();
    }

    public void destroy() {
        notiClient.destory();
    }

    public void sendControlMessage(String productKey, String mac, String did, Map attrs) {
        notiClient.sendControlMessage(productKey, mac, did, attrs);
    }

    public void sendControlMessage(String productKey, String mac, String did, DataCommand cmd, Byte[] raw) {
        notiClient.sendControlMessage(productKey, mac, did, cmd, raw);
    }

    public void sendControlMessage(List<RemoteControlData> controlMessage) {
        notiClient.sendControlMessage(controlMessage);
    }


    /**
     * 消息处理
     */
    public void receiveMessage() {
        new Thread() {
            public void run() {
                //订阅(接收)推送事件消息
                String message = null;
                while ((message = notiClient.receiveMessage()) != null) {
                    logger.info("实时接收snoti消息:" + message);
                    JsonObject jsonObject = new JsonParser().parse(message).getAsJsonObject();
                    String eventType = jsonObject.get("event_type").getAsString().toUpperCase();
                    String cmd = jsonObject.get("cmd").getAsString();

                    Command command = Command.getCmd(cmd);
                    PushEvents events = PushEvents.valueOf(eventType);
                    // 只处理推送消息
                    try {
                        if (command.equals(Command.EVENT_PUSH)) {
                            Iterator<Map.Entry<PushEvents, IPushEvent>> it = callbacks.entrySet().iterator();
                            while (it.hasNext()) {
                                Map.Entry<PushEvents, IPushEvent> callback = it.next();
                                if (events.equals(callback.getKey())) {
                                    callback.getValue().callback(message);
                                }
                            }
                        }
                    } catch (Exception e) {
                        logger.error("snoti 推送消息", e);
                    }
                }
            }
        }.start();

    }

    public void registerCallbackEvent(PushEvents pushEvents, IPushEvent pushEventCallback) {
        callbacks.put(pushEvents, pushEventCallback);
    }


}
